//! 事件的主体结构
//!
use crate::error::Error;
use serde::{Deserialize, Serialize};
use std::{
    ops::{Deref, DerefMut},
    str::FromStr,
};

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct EventBody {
    pub shared_id: i32,
    pub creator_id: i64,
    pub creator_seq: i64,
    pub other_id: i64,
    pub other_seq: i64,
    pub time_created: i64,
    pub is_famous: bool,
    pub tans: Vec<Vec<u8>>,
    pub signature: Vec<u8>,
    pub generation: i64, // 这个可以再网络上传输也可以不传输，如果不传输则需要按照generation排序后发送
    pub hash: Vec<u8>, // 这个值不用在网络上传输，由获得者根据两个父亲的hash自行计算。这样一方面节约了传输带宽，另一方面即使传输了，接受者也要重新计算以验证，确保内容没有被篡改
    pub cons_timestamp: i64,
    pub other_hash: Vec<u8>,
    pub parent_hash: Vec<u8>,
    pub trans_count: BigInt,
    pub cons_event_count: BigInt,
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct BigInt(num_bigint::BigInt);

impl BigInt {
    pub fn new(value: num_bigint::BigInt) -> Self {
        Self(value)
    }

    pub fn bigint(&self) -> &num_bigint::BigInt {
        &self.0
    }
}

impl Deref for BigInt {
    type Target = num_bigint::BigInt;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for BigInt {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

impl From<num_bigint::BigInt> for BigInt {
    fn from(value: num_bigint::BigInt) -> Self {
        Self(value)
    }
}
impl From<&num_bigint::BigInt> for BigInt {
    fn from(value: &num_bigint::BigInt) -> Self {
        Self(value.clone())
    }
}

impl Into<num_bigint::BigInt> for BigInt {
    fn into(self) -> num_bigint::BigInt {
        self.0
    }
}

impl Into<num_bigint::BigInt> for &BigInt {
    fn into(self) -> num_bigint::BigInt {
        self.0.clone()
    }
}

impl Serialize for BigInt {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_str(&self.0.to_string())
    }
}
impl<'de> Deserialize<'de> for BigInt {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        struct BigIntVisitor;
        impl<'de> serde::de::Visitor<'de> for BigIntVisitor {
            type Value = BigInt;

            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                formatter.write_str("an integer between -2^31 and 2^31")
            }

            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
            where
                E: serde::de::Error,
            {
                let inner =
                    num_bigint::BigInt::from_str(v).map_err(|e| E::custom(e.to_string()))?;
                Ok(BigInt(inner))
            }
        }

        deserializer.deserialize_str(BigIntVisitor)
    }
}

impl Default for EventBody {
    fn default() -> Self {
        Self {
            shared_id: Default::default(),
            creator_id: Default::default(),
            creator_seq: Default::default(),
            other_id: Default::default(),
            other_seq: Default::default(),
            time_created: 0,
            is_famous: Default::default(),
            tans: Default::default(),
            signature: Default::default(),
            generation: 0,
            hash: Vec::new(),
            cons_timestamp: 0,
            other_hash: Vec::new(),
            parent_hash: Vec::new(),
            trans_count: BigInt::default(),
            cons_event_count: BigInt::default(),
        }
    }
}

impl EventBody {
    /// 和一个json字符串进行比较
    pub fn eq(&self, json: &str) -> Result<bool, Error> {
        let e: EventBody = serde_json::from_str(json)?;
        Ok(self == &e)
    }
}

impl PartialEq for EventBody {
    fn eq(&self, other: &Self) -> bool {
        self.shared_id == other.shared_id
            && self.creator_id == other.creator_id
            && self.creator_seq == other.creator_seq
            && self.other_id == other.other_id
            && self.other_seq == other.other_seq
            && self.time_created == other.time_created
            && self.is_famous == other.is_famous
            && self.tans == other.tans
            && self.signature == other.signature
            && self.generation == other.generation
            && self.hash == other.hash
            && self.cons_timestamp == other.cons_timestamp
            && self.other_hash == other.other_hash
            && self.parent_hash == other.parent_hash
            && self.trans_count == other.trans_count
            && self.cons_event_count == other.cons_event_count
    }
}

impl Eq for EventBody {}
